﻿
using System.Collections.Generic;
using System.Linq;
using Castle.Core.Interceptor;
using ElectronicCommerce.Framework.Ioc.Interceptor.Configuration;

namespace ElectronicCommerce.Framework.Ioc.Interceptor.Infos
{
    /// <summary>
    /// Intercepter Base
    /// </summary>
    public abstract class IntercepterBase : IInterceptor
    {
        #region Fields

        public List<MethodInfo> UseMethodInfos { private get; set; }
        public List<MethodInfo> NotUseMethodInfos { private get; set; }

        #endregion

        #region IInterceptor Members

        public void Intercept(IInvocation invocation)
        {
            if ((UseMethodInfos == null && NotUseMethodInfos == null) ||
                IsMethodCanbeUse(invocation.Method.Name, invocation.Arguments))
            {
                Process(invocation);
            }
            invocation.Proceed();
        }

        #endregion

        #region Abstractor methods

        public abstract void Process(IInvocation invocation);

        #endregion

        #region Helper

        private bool IsMethodCanbeUse(string name, object[] arguments)
        {
            #region Check

            if (UseMethodInfos == null && NotUseMethodInfos != null)
            {
                if (NotUseMethodInfos.Count(c => c.Name == name) == 0)
                {
                    return true;
                }
            }

            if (UseMethodInfos != null && NotUseMethodInfos == null)
            {
                if (UseMethodInfos.Count(c => c.Name == name) == 0)
                {
                    return false;
                }
            }

            MethodInfo curtMethod = null;

            if (UseMethodInfos != null && UseMethodInfos.Count(c => c.Name == name) > 0)
            {
                curtMethod = UseMethodInfos.Where(c => c.Name == name).First();
            }
            else if (NotUseMethodInfos != null && NotUseMethodInfos.Count(c => c.Name == name) > 0)
            {
                curtMethod = NotUseMethodInfos.Where(c => c.Name == name).First();
            }

            if (curtMethod == null)
            {
                return false;
            }

            #endregion

            //all method is pass
            if (curtMethod.Parameters == null || curtMethod.Parameters.Count == 0)
            {
                return curtMethod.IsUseIntercepter ? true : false;
            }

            //has paramters
            if (arguments != null && arguments.Count() > 0)
            {
                #region Validate params

                //params' count different
                if (arguments.Count() != curtMethod.Parameters.Count
                    && curtMethod.IsUseIntercepter)
                {
                    return false;
                }

                for (int i = 0; i < arguments.Count(); i++)
                {
                    if (curtMethod.Parameters[i].GetType() != arguments[i].GetType()
                        && curtMethod.IsUseIntercepter)
                    {
                        return false;
                    }
                }

                #endregion

                return true;
            }
            //no paramters
            return curtMethod.IsUseIntercepter ? false : true;

        }
        #endregion
    }
}
